{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "-N59E9S4BzSr"
   },
   "source": [
    "##### Copyright 2023 The Cirq Developers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "cellView": "form",
    "id": "_SAdH7I0B2rz"
   },
   "outputs": [],
   "source": [
    "# @title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "# https://www.apache.org/licenses/LICENSE-2.0\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "NZv6mLU-B_b0"
   },
   "source": [
    "# Getting set up to use Google's quantum processors"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "vBsLfco2CD12"
   },
   "source": [
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://quantumai.google/cirq/tutorials/google/start\"><img src=\"https://quantumai.google/site-assets/images/buttons/quantumai_logo_1x.png\" />View on QuantumAI</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/quantumlib/Cirq/blob/main/docs/tutorials/google/start.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/colab_logo_1x.png\" />Run in Google Colab</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/quantumlib/Cirq/blob/main/docs/tutorials/google/start.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/github_logo_1x.png\" />View source on GitHub</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a href=\"https://storage.googleapis.com/tensorflow_docs/Cirq/docs/tutorials/google/start.ipynb\"><img src=\"https://quantumai.google/site-assets/images/buttons/download_icon_1x.png\" />Download notebook</a>\n",
    "  </td>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "fe7e28f44667"
   },
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "846b32703c5c"
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    import cirq\n",
    "    import cirq_google as cg\n",
    "except ImportError:\n",
    "    print(\"installing cirq-google and cirq...\")\n",
    "    !pip install --quiet cirq-google cirq\n",
    "    print(\"installed cirq-google and cirq.\")\n",
    "    import cirq\n",
    "    import cirq_google as cg"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "So5iLqkNPnFm"
   },
   "source": [
    "Access to Google's quantum processors is mediated through the Quantum Engine service. This notebook is a tutorial to get you started with the typical setup, using the open source Python framework [Cirq](https://github.com/quantumlib/Cirq), in the free cloud Jupyter notebook environment, [Google Colab](https://colab.research.google.com/).\n",
    "\n",
    "Access is currently restricted to those in an approved group, and you must be in that group before running this tutorial.\n",
    "\n",
    "You can find more about running this in colaboratory in the [Colab documentation](https://colab.research.google.com/notebooks/welcome.ipynb) or in our Cirq-specific guide to [running in Colab](colab.ipynb).  You can download this notebook from the [GitHub repository](https://github.com/quantumlib/Cirq/blob/main/docs/tutorials/google/start.ipynb)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "da8NOLsZqLsU"
   },
   "source": [
    "## Before you begin\n",
    "\n",
    "*  First, decide whether you want to [create a new Google Cloud Platform project](https://cloud.google.com/docs/overview/), or use an existing one.\n",
    "*  Follow this link to [**enable the Quantum Engine API**](https://console.cloud.google.com/apis/library/quantum.googleapis.com?returnUrl=quantum) in your Google Cloud Platform project.\n",
    "\n",
    "After the API is enabled, you should be redirected to the [Quantum Engine console](https://console.cloud.google.com/quantum) and it should look like the following screenshot.\n",
    "\n",
    "![Quantum Engine landing](https://raw.githubusercontent.com/quantumlib/Cirq/main/docs/images/console-landing.png)\n",
    "\n",
    "**Enter your project id into the input text box below**. To find your project id, click on the project menu in the blue bar at the top of the console. This will open a menu that displays your project name (e.g. \"My project\") and unique **project id** (e.g. my-project-1234). Enter the **project id** into the input below. ([Help on finding your project id](https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects).)\n",
    "\n",
    "![Find project id](https://raw.githubusercontent.com/quantumlib/Cirq/main/docs/images/console-project-id.png)\n",
    "\n",
    "**Run the code in the next block (the one with the text box)**, which will prompt you to authenticate Google Cloud SDK to use your project.  After running the block, you will see a link which you should click.  This will open a new browser window.  Follow the authentication flow for this window.  If you see \"Authentication complete\" you have done this step successfully. Contact your partner in the Quantum Hardware Residency Program if you encounter issues at this stage.\n",
    "\n",
    "![Run code block below](https://raw.githubusercontent.com/quantumlib/Cirq/main/docs/images/run-code-block.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "YoqI9GrOPExP"
   },
   "outputs": [],
   "source": [
    "# The Google Cloud Project id to use.\n",
    "project_id = \"\"  # @param {type:\"string\"}\n",
    "\n",
    "from cirq_google.engine import get_engine\n",
    "from cirq_google.engine.qcs_notebook import authenticate_user\n",
    "\n",
    "authenticate_user()\n",
    "try:\n",
    "    engine = get_engine(project_id)\n",
    "except Exception:\n",
    "    from cirq_google.engine.qcs_notebook import get_qcs_objects_for_notebook\n",
    "\n",
    "    print(\"Unable to connect to a hardware engine. Using a virtual instance instead.\")\n",
    "    qcs_objects = get_qcs_objects_for_notebook(project_id, virtual=True)\n",
    "    engine = qcs_objects.engine"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ocy3JossWU57"
   },
   "source": [
    "**Authentication details**\n",
    "\n",
    "Double clicking on the project_id block above will expose the code that is run when you run this code block.  This code ensures that *Application Default Credentials* are set and can be used in Cirq to authenticate your calls to Quantum Engine.\n",
    "\n",
    "If you are going to run code outside of colab and want to authenticate, see the below section on running from the command-line."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "47n3bsx3Nl9g"
   },
   "source": [
    "## Create a circuit\n",
    "Now, let's create a basic program with Cirq. After reviewing the code, **run this block** to run a circuit, and print a circuit diagram and results. To learn more, refer to the [Cirq overview](https://quantumai.google/cirq) and [Cirq basics](https://quantumai.google/cirq/start/basics) pages."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "cellView": "both",
    "id": "EQoTYZIEPa9S"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Circuit:\n",
      "(0, 0): ───X───M('result')───\n"
     ]
    }
   ],
   "source": [
    "# Define a qubit at an arbitrary grid location.\n",
    "qubit = cirq.GridQubit(0, 0)\n",
    "\n",
    "# Create a circuit (qubits start in the |0> state).\n",
    "circuit = cirq.Circuit(\n",
    "    cirq.X(qubit), cirq.measure(qubit, key='result')  # NOT gate.  # Measurement.\n",
    ")\n",
    "\n",
    "print(\"Circuit:\")\n",
    "print(circuit)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "BJIWCdhKgVo7"
   },
   "source": [
    "## Simulate the circuit using Cirq\n",
    "\n",
    "Let's quickly use Cirq to simulate the circuit above."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "TW_zU_pagVP0"
   },
   "outputs": [],
   "source": [
    "# Simulate the circuit, repeating 1000 times.\n",
    "print(\"Simulating circuit using Cirq...\\n\")\n",
    "results = cirq.sample(circuit, repetitions=1000)\n",
    "print(\"Measurement results:\")\n",
    "print(results)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "4ZK4GQWmyo-u"
   },
   "source": [
    "## Run on quantum hardware\n",
    "Approved users have access to a processor in \"open-swim\" mode that runs jobs on a first-in-first-out basis per user, with a fairness algorithm that balances jobs across users. To see which processors you have access to, you can either visit the [Cloud Console](https://console.cloud.google.com/quantum/processors) or call `list_processors()` on an `Engine` object."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "uz0xSlml3fkA"
   },
   "source": [
    "### Create a Quantum Engine client\n",
    "Interactions with hardware are facilitated by the Quantum Computing Service. A client must first be initialized with your Google Cloud project to perform these interactions.\n",
    "\n",
    "You can create a client to the service as follows:\n",
    "\n",
    "`engine = cg.Engine(project_id=YOUR_PROJECT_ID)`\n",
    "\n",
    "Note: for this tutorial, we already initialized a variable `engine`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Msw_waVhQBLF"
   },
   "source": [
    "### Select a quantum processor\n",
    "Before running an experiment, you must first specify the processor on which you'd like to run. Please work with your internal point-of-contact to help decide which processor is most appropriate and to set expectations for how to best collaborate on the device.\n",
    "\n",
    "You can view the processors available to you in the [Cloud Console](https://console.cloud.google.com/quantum/processors) or with a call to `engine.list_processors()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "rvMeXrC1wnQi"
   },
   "outputs": [],
   "source": [
    "processors = [p.processor_id for p in engine.list_processors() if p.health() == 'OK']\n",
    "print(f\"Available processors: {processors}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "m04izoTAu06T"
   },
   "source": [
    "After selecting your device, enter its ID in the following code block and run it as well.\n",
    "\n",
    "![Run code block below](https://raw.githubusercontent.com/quantumlib/Cirq/main/docs/images/run-code-block.png)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "cellView": "form",
    "id": "sFNJgR60Pufg"
   },
   "outputs": [],
   "source": [
    "processor_id = \"\"  # @param {type:\"string\"}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "FS42e_sx0Hqw"
   },
   "source": [
    "### View the processor's topology\n",
    "Each processor has a set of available qubits laid out on a grid with limited couplings between qubits. The device specification can be printed to inspect the topology of a processor."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "O-Jrib9y1TFY"
   },
   "outputs": [],
   "source": [
    "id = processor_id or processors[0]\n",
    "processor = engine.get_processor(id)\n",
    "\n",
    "# Print the device showing qubit connectivity.\n",
    "device = processor.get_device()\n",
    "print(device)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "bJ7ePCCNrh82"
   },
   "source": [
    "Note that the qubit that we used for the simulation above, `(0, 0)`, does not exist on the hardware. Since the grid of available qubits may change over time, we'll programatically select a valid qubit by inspecting `device.qubits`. We then use the `transform_qubits()` method to remap the circuit onto that qubit.\n",
    "\n",
    "In order to run on hardware, we must also ensure that the circuit only contains gates that the hardware supports. The basic gates used here are always available, so this circuit can be run without any further changes, but in general you may need to apply additional transformations before running arbitrary circuits. See the [best practices](https://quantumai.google/cirq/google/best_practices) guide for more information about running circuits on hardware."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "ma8JDhTUR389"
   },
   "outputs": [],
   "source": [
    "valid_qubit = sorted(device.metadata.qubit_set)[0]\n",
    "\n",
    "# Transform circuit to use an available hardware qubit.\n",
    "hw_circuit = circuit.transform_qubits(lambda q: valid_qubit)\n",
    "\n",
    "print(hw_circuit)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "e-tOIGJD9c9_"
   },
   "source": [
    "Among these best practices, we will highlight two important ones.\n",
    "\n",
    "First, if your circuit uses more than one qubit, you can map the circuit onto the grid of the quantum processor in a way that accounts for its topology. You can do this as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "LQh5D_Mx9hvk"
   },
   "outputs": [],
   "source": [
    "device_graph = device.metadata.nx_graph\n",
    "router = cirq.RouteCQC(device_graph)\n",
    "hw_circuit = router(circuit)\n",
    "print(hw_circuit)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "3An1Uo6F9vxS"
   },
   "source": [
    "Second, if your quantum processor is calibrated to do a specific set of gates, you will need to transform your circuit into that gateset. For example, for a CZ gateset, you can do the following."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "muJ-dprf9_HC"
   },
   "outputs": [],
   "source": [
    "gateset = cirq.CZTargetGateset(allow_partial_czs=True)\n",
    "transformed_circuit = cirq.optimize_for_target_gateset(hw_circuit, gateset=gateset)\n",
    "print(transformed_circuit)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "hmIT53Yv5RR1"
   },
   "source": [
    "Other gatesets and considerations are included in the [best practices guide](https://quantumai.google/cirq/google/best_practices)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "TH4vtUeq2ryV"
   },
   "source": [
    "### Sample from a circuit on the Quantum Engine\n",
    "\n",
    "Experiments can be performed  on the Quantum Computing Service by _sampling_ from a circuit. A [`Sampler`](https://quantumai.google/reference/python/cirq/Sampler) encapsulates the setup details of an experiment. You can retrieve a Sampler from the Processor object we created above to collect samples from that processor.\n",
    "\n",
    "An un-parameterized call to `get_sampler()` will run with that processor's default configuration, but we support custom device layouts and calibrations to achieve the highest possible performance on the device for a given experiment. To use these features today, you'll need to work with an internal partner to supply you with the necessary configurations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "bWeeaRUtllBY"
   },
   "outputs": [],
   "source": [
    "sampler = processor.get_sampler(\n",
    "    # Get these values from an internal partner:\n",
    "    # device_config_name='layout_42',\n",
    "    # run_name='2023.11.06-1.0',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "NRUCVZP0lr3A"
   },
   "source": [
    "The execution of your experiment will likely be completed within a few seconds and the results will be displayed below. The output will include a link to the [console](https://console.cloud.google.com/quantum), where you can track the status and results of \"jobs\" spawned by your experiments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "-a0I0cbGyivS"
   },
   "outputs": [],
   "source": [
    "print(\"Scheduling execution on the Quantum Engine...\\n\")\n",
    "print(\n",
    "    \"You can view jobs at: https://console.cloud.google.com/quantum/\"\n",
    "    \"jobs?project={}\\n\".format(project_id)\n",
    ")\n",
    "\n",
    "# Print out the results. This blocks until the results are returned.\n",
    "results = sampler.run(hw_circuit, repetitions=1000)\n",
    "cirq.plot_state_histogram(results)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "3u4dLfDugI9l"
   },
   "source": [
    "## Running from the command line\n",
    "\n",
    "If you are planning to access Quantum Computing Service from the command line, follow these instructions to get started.  If you plan on executing all of your programs from an ipython notebook, you can skip this section.\n",
    "\n",
    "### Set up Cirq\n",
    "\n",
    "Follow the [Cirq Install](https://quantumai.google/cirq/start/install) page to install Cirq locally. We highly recommend that you set up a Python virtual environment for this installation to isolate your development stack from your overall system installations. Make sure to setup the virtual environment for Python 3 and not Python 2.\n",
    "\n",
    "### Set up Google Cloud authentication\n",
    "\n",
    "In this quickstart we will authenticate using the gcloud command line cool.  To do this, one must first install gcloud.  Follow the instructions for this at https://cloud.google.com/sdk/install. We will authenticate using Application Default Credentials.  To do this simply run the following on your shell command line\n",
    "\n",
    "`gcloud auth application-default login`\n",
    "\n",
    "This will open up a browser window or give you a link to a webpage you can navigate to in order to go through an authentication flow.  Complete this using your Google account.  After this command is run, credentials will be stored on your local machine.  If at any point you want to revoke these credentials you can run `gcloud auth application-default revoke`. These credendtials typically\n",
    "need to be renewed once each day.\n",
    "\n",
    "It is recommended that your colab runs using Python 3.11 or greater."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "quSdrNseg8LC"
   },
   "source": [
    "### Write and run a short quantum program\n",
    "\n",
    "Using your favorite IDE or editor, read and then paste the following hello_qubit program into a file called `hello_qubit.py`.  Make sure to replace the `'your-project-id'` string with the project id you created above.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "4RXHE070gleY"
   },
   "outputs": [],
   "source": [
    "import cirq\n",
    "import cirq_google as cg\n",
    "\n",
    "\n",
    "def example(engine, processor_id):\n",
    "    \"\"\"Hello qubit example run against a quantum processor.\"\"\"\n",
    "\n",
    "    # Define a qubit on the device.\n",
    "    processor = engine.get_processor(processor_id)\n",
    "    qubit = sorted(processor.get_device().metadata.qubit_set)[0]\n",
    "\n",
    "    # Create a circuit (qubits start in the |0> state).\n",
    "    circuit = cirq.Circuit(\n",
    "        cirq.X(qubit) ** 0.5,  # Square root of NOT.\n",
    "        cirq.measure(qubit, key='result'),  # Measurement.\n",
    "    )\n",
    "\n",
    "    sampler = processor.get_sampler()\n",
    "    print(\"Sampling circuit on Quantum Engine...\\n\")\n",
    "    results = sampler.run(circuit, repetitions=1000)\n",
    "\n",
    "    print(\"\\nMeasurement results:\")\n",
    "    print(results)\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    # Set up QCS objects.\n",
    "    from cirq_google.engine.qcs_notebook import get_qcs_objects_for_notebook\n",
    "\n",
    "    qcs_objects = get_qcs_objects_for_notebook(project_id='')\n",
    "    processor_id = qcs_objects.processor_id\n",
    "    engine = qcs_objects.engine\n",
    "\n",
    "    example(engine, processor_id)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "TjYi3VOTgyvh"
   },
   "source": [
    "Once saved, you can  run this program from the command line:\n",
    "\n",
    "```\n",
    "python hello_qubit.py\n",
    "```\n",
    "\n",
    "Upon successful completion, the script will print the sampled bitstring."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "WCKQ1lIJSgJ7"
   },
   "source": [
    "## Next steps\n",
    "* Use [this template colab](https://quantumai.google/cirq/tutorials/google/colab) as a base for your own explorations.\n",
    "* Explore [best practices](https://quantumai.google/cirq/google/best_practices) for getting circuits to run on hardware.\n"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "start.ipynb",
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
